﻿using System.IO;
using System.Security.Cryptography;//
using System;
using System.Text;
using System.Collections.Generic;
using LitJson;

public static class MD5Helper
{
    /// <summary>
    ///     /// <summary>
    /// 对比两个文件列表,获取需要更新的文件名
    /// </summary>
    /// <param name="jsonLocal">本地FileList.json字符串</param>
    /// <param name="JsonRemote">服务器FileList.json字符串</param>
    /// <param name="totalSize">需要跟新的文件总大小</param>
    /// <returns></returns>
    public static List<string> CompareFileListJson(string jsonLocal, string JsonRemote, out long totalSize)
    {
        var listUpdate = new List<string>();
        var listLocal = JsonMapper.ToObject<List<Dictionary<string, string>>>(jsonLocal);
        var listRemote = JsonMapper.ToObject<List<Dictionary<string, string>>>(JsonRemote);
        totalSize = 0;
        for (int i = 0; i < listRemote.Count; i++)
        {
            var infoR = listRemote[i];
            //服务器有本地没有的
            if (!ListHelper.Find(listLocal, p => p["fileName"] == infoR["fileName"], out var InfoL))
            {
                totalSize += long.Parse(infoR["size"]);
                listUpdate.Add(infoR["fileName"]);
            }
            //服务器有本地也有,对比一下MD5值
            else
            {
                if (infoR["md5"] != InfoL["md5"])
                {
                    totalSize += long.Parse(infoR["size"]);
                    listUpdate.Add(infoR["fileName"]);
                }
            }
        }

        return listUpdate;
    }

    public static string CreatMD5List_json(string dir, string excludeExtension = null)
    {
        //文件:文件信息
        //文件信息>md5,大小
        List<Dictionary<string, string>> list = new List<Dictionary<string, string>>();

        ForEveryFile(dir, filePath =>
        {
            //排除一些特殊后缀的文件
            string fileExtemsion = Path.GetExtension(filePath);
            if (excludeExtension == null || !excludeExtension.Contains(fileExtemsion) || fileExtemsion == "")
            {
                if (filePath != Path.Combine(dir, "FileList.json"))
                {
                    dir = dir.EndsWith("\\") ? dir : dir + "\\";
                    string shortPath = filePath.Replace(dir, "");       //得到相对路径
                    string md5 = GetFileMD5(filePath);                     //得到MD5值
                    long size = new FileInfo(filePath).Length;          //得到文件大小
                    var dic = new Dictionary<string, string>();
                    dic["fileName"] = shortPath;
                    dic["md5"] = md5;
                    dic["size"] = size.ToString();
                    list.Add(dic);
                }
            }
        });
        string jsonStr = LitJson.JsonMapper.ToJson(list);

        File.WriteAllText(Path.Combine(dir, "FileList.json"), jsonStr);

        UnityEngine.Debug.Log("生成文件md5清单完成");
        return jsonStr;
    }

    /// <summary>
    /// 生成目录下所有文件的MD5值清单并保存
    /// </summary>
    /// <param name="dir"></param>
    /// <param name="savePath"></param>
    public static string CreatMD5List_Txt(string dir, string savePath = null)    //格式   a.exe  "asd4f4a4sf564a6sd1fasd5f4af5"  1245
    {
        StringBuilder sb = new StringBuilder();
        dir = dir.EndsWith("\\") ? dir : dir + "\\";
        ForEveryFile(dir, file =>
        {
            if (file != Path.Combine(dir, "FileList.json"))
            {
                if (Path.GetFileName(file) == Path.GetFileName(savePath)) return;
                long size = new FileInfo(file).Length;          //得到文件大小
                sb.AppendFormat("{0}\t{1}\t{2}\n", file.Replace(dir, ""), GetFileMD5(file), size);
            }
        });
        File.WriteAllText(Path.Combine(dir, "FileList.text"), sb.ToString());
        return sb.ToString();
    }

    private static void ForEveryFile(string dir, Action<string> action)
    {
        string[] files = Directory.GetFiles(dir);
        for (int i = 0; i < files.Length; i++)
        {
            action(files[i]);
        }

        string[] subDirs = Directory.GetDirectories(dir);
        foreach (var item in subDirs)
        {
            ForEveryFile(item, action);
        }
    }

    /// <summary>
    /// 获取一个文件的MD5值
    /// </summary>
    /// <param name="filePath"></param>
    /// <returns></returns>
    public static string GetFileMD5(string filePath)
    {
        FileStream fs = new FileStream(filePath, FileMode.Open);
        int len = (int)fs.Length;
        byte[] data = new byte[len];
        fs.Read(data, 0, len);
        fs.Close();
        MD5 md5 = new MD5CryptoServiceProvider();
        byte[] result = md5.ComputeHash(data);
        string fileMD5 = "";
        foreach (byte b in result)
        {
            fileMD5 += Convert.ToString(b, 16);
        }
        return fileMD5;
    }
}